package com.alks.function.service.impl.finance.mtlcosts;

import com.alks.common.aop.AutoPageAop;
import com.alks.common.data.dto.SysUserTokenDTO;
import com.alks.common.data.thread.UserIdThread;
import com.alks.common.utils.DateUtils;
import com.alks.common.utils.beanutils.ArrayUtils;
import com.alks.entity.data.entity.PcCostDetail;
import com.alks.entity.data.entity.PcCostDetail2;
import com.alks.entity.data.entity.PcSupplementDutyTtl;
import com.alks.entity.data.enums.SlipTypeEnum;
import com.alks.entity.data.response.ResponseInfo;
import com.alks.function.data.dto.finance.mtlcosts.FinSuppDutyTtl2Dto;
import com.alks.function.data.request.finance.mtlcosts.SuppDutyTtlFindRequest;
import com.alks.function.data.request.finance.mtlcosts.SuppDutyTtlQueryRequest;
import com.alks.function.mapper.finance.mtlcosts.PcCostDetail2Mapper;
import com.alks.function.mapper.finance.mtlcosts.PcCostDetailMapper;
import com.alks.function.mapper.finance.mtlcosts.PcSupplementDutyTtlMapper;
import com.alks.function.service.finance.mtlcosts.ISuppDutyFinaService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import jodd.util.StringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author MS
 * @since 2024/6/22下午5:10
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class SuppDutyFinaServiceImpl extends ServiceImpl<PcSupplementDutyTtlMapper, PcSupplementDutyTtl> implements ISuppDutyFinaService {
    private final PcSupplementDutyTtlMapper ttlMapper;
    private final PcCostDetailMapper costMapper;
    private final PcCostDetail2Mapper cost2Mapper;

    @Override
    @AutoPageAop
    public Map<String, Object> suppDutyTtlQuery(SuppDutyTtlQueryRequest request) {
        SysUserTokenDTO tokenDTO = UserIdThread.get();
        String companyId = tokenDTO.getCompanyId();
        /*获取数据*/
        List<FinSuppDutyTtl2Dto> dtos = ttlMapper.suppDutyTtlQuery(request, companyId);
        /*获取求和数据*/
        Map<String, BigDecimal> sumMap = ttlMapper.suppDutyTtlSumQuery(request, companyId);
        Map<String, Object> map = new HashMap<>(3);
        map.put("dtos", dtos);
        map.put("sum", sumMap);
        if (!request.getPageSize().equals(-1)&&!request.getPageNum().equals(-1)){
            Page<FinSuppDutyTtl2Dto> page = (Page<FinSuppDutyTtl2Dto>) dtos;
            map.put("total", page.getTotal());
        }
        return map;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseInfo suppDutyTtlFinance(List<SuppDutyTtlFindRequest> request, String financeYymm, String accountName, Integer flag, String remark) {
        SysUserTokenDTO tokenDTO = UserIdThread.get();
        String companyId = tokenDTO.getCompanyId();
        String userName = tokenDTO.getUserName();
        int check = 1;
        int uncheck = 0;
        /*入参健壮性检验*/
        if (ArrayUtils.isEmpyt(request)) {
            return ResponseInfo.error("请选择材料");
        }
        if (flag.equals(check)) {
            if (StringUtil.isBlank(financeYymm)) {
                return ResponseInfo.error("结算月份不能为空");
            }
            if (StringUtil.isBlank(accountName)) {
                return ResponseInfo.error("结算方式不能为空");
            }
            DateUtils.financeYymmCheck(financeYymm);
        }
        /*判断数据是否可以结算*/
        LambdaUpdateWrapper<PcSupplementDutyTtl> wrapper = new LambdaUpdateWrapper<PcSupplementDutyTtl>()
                .eq(PcSupplementDutyTtl::getCompanyId, companyId);
        LambdaUpdateWrapper<PcCostDetail> costWrapper = new LambdaUpdateWrapper<PcCostDetail>()
                .eq(PcCostDetail::getCompanyId, companyId);
        LambdaUpdateWrapper<PcCostDetail2> cost2Wrapper = new LambdaUpdateWrapper<PcCostDetail2>()
                .eq(PcCostDetail2::getCompanyId, companyId);
        wrapper.and(w->{
            for (SuppDutyTtlFindRequest r : request) {
                w.or(w1->w1.eq(PcSupplementDutyTtl::getSlipNo, r.getSlipNo())
                        .eq(PcSupplementDutyTtl::getDutyName,r.getDutyName()));
            }
            return w;
        });
        costWrapper.and(w->{
            for (SuppDutyTtlFindRequest r : request) {
                w.or(w1->w1.eq(PcCostDetail::getSlipNo, r.getSlipNo())
                        .eq(PcCostDetail::getVendorName,r.getDutyName()));
            }
            return w;
        });
        cost2Wrapper.and(w->{
            for (SuppDutyTtlFindRequest r : request) {
                w.or(w1->w1.eq(PcCostDetail2::getSlipNo, r.getSlipNo())
                        .eq(PcCostDetail2::getVendorName,r.getDutyName()));
            }
            return w;
        });
        if (flag.equals(check)||flag.equals(uncheck)) {
            /*如果已有结算单号则不能操作*/
            LambdaUpdateWrapper<PcCostDetail> detailWrapper1 = costWrapper.clone();
            detailWrapper1.isNotNull(PcCostDetail::getBalanceNo);
            List<PcCostDetail> details = costMapper.selectList(detailWrapper1);
            if (ArrayUtils.isNoEmpyt(details)) {
                return ResponseInfo.error("结算应付已结算，不能操作");
            }
            LambdaUpdateWrapper<PcCostDetail2> detailWrapper2 = cost2Wrapper.clone();
            detailWrapper2.isNotNull(PcCostDetail2::getBalanceNo);
            List<PcCostDetail2> details2 = cost2Mapper.selectList(detailWrapper2);
            if (ArrayUtils.isNoEmpyt(details2)) {
                return ResponseInfo.error("人工薪资已结算，不能操作");
            }
            /*判断是否重复结算或取消结算*/
            LambdaUpdateWrapper<PcSupplementDutyTtl> wrapper1 = wrapper.clone();
            if (flag.equals(check)) {
                wrapper1.eq(PcSupplementDutyTtl::getCfmFlag, "Y");
            } else {
                wrapper1.isNull(PcSupplementDutyTtl::getCfmFlag);
            }
            List<PcSupplementDutyTtl> checkErrTtls = ttlMapper.selectList(wrapper1);
            if (!ArrayUtils.isEmpyt(checkErrTtls)) {
                String msg = "Y".equals(checkErrTtls.get(0).getCfmFlag()) ? "已结算" : "未结算";
                return ResponseInfo.error("包括订单号【" + checkErrTtls.get(0).getSlipNo() + "】在内" + checkErrTtls.size() + "条数据" + msg);
            }
            /*进行对账作业*/
            if (flag.equals(check)) {
                wrapper.set(PcSupplementDutyTtl::getCfmFlag, "Y")
                        .set(PcSupplementDutyTtl::getCfmUser, userName)
                        .set(PcSupplementDutyTtl::getCfmDate, LocalDate.now())
                        .set(PcSupplementDutyTtl::getAccountName, accountName)
                        .set(PcSupplementDutyTtl::getFinanceYymm, financeYymm);
            } else {
                wrapper.set(PcSupplementDutyTtl::getCfmFlag, null)
                        .set(PcSupplementDutyTtl::getCfmUser, null)
                        .set(PcSupplementDutyTtl::getCfmDate, null)
                        .set(PcSupplementDutyTtl::getAccountName, null)
                        .set(PcSupplementDutyTtl::getFinanceYymm, null);
            }
        }
        wrapper.set(PcSupplementDutyTtl::getRemark,remark);
        ttlMapper.update(null, wrapper);
        /*写入费用结算表*/
        if (flag.equals(check)) {
            cost2Mapper.suppDutyTtlFinance(request,companyId,userName,financeYymm,accountName);
            costMapper.suppDutyTtlFinance(request, companyId, userName,financeYymm,accountName);
        } else if (flag.equals(uncheck)){
            costMapper.delete(costWrapper);
            cost2Mapper.delete(cost2Wrapper);
        }
        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo mtlPreOtherInBack() {
        String companyId = UserIdThread.get().getCompanyId();
        /*补料类型*/
        List<String> blFlag = SlipTypeEnum.SlipNameList();
        /*责任归属*/
        LambdaQueryWrapper<PcSupplementDutyTtl> wrapperDept = new LambdaQueryWrapper<PcSupplementDutyTtl>()
                .select(PcSupplementDutyTtl::getDeptName, PcSupplementDutyTtl::getDeptNo)
                .eq(PcSupplementDutyTtl::getCompanyId, companyId)
                .groupBy(PcSupplementDutyTtl::getDeptNo);
        List<PcSupplementDutyTtl> deptTtls = ttlMapper.selectList(wrapperDept);
        List<Map<String, String>> dept = new ArrayList<>();
        if (!ArrayUtils.isEmpyt(deptTtls)) {
            dept = deptTtls.stream()
                    .filter(Objects::nonNull)
                    .filter(a -> StringUtil.isNotBlank(a.getDeptNo()))
                    .map(a->{Map<String,String> map=new HashMap<>();
                    map.put("deptNo",a.getDeptNo());
                    map.put("deptName",a.getDeptName());
                    return map;})
                    .collect(Collectors.toList());
        }
        /*部门回显*/
        LambdaQueryWrapper<PcSupplementDutyTtl> wrapperDuty = new LambdaQueryWrapper<PcSupplementDutyTtl>()
                .select(PcSupplementDutyTtl::getDutyName)
                .eq(PcSupplementDutyTtl::getCompanyId, companyId)
                .groupBy(PcSupplementDutyTtl::getDutyName);
        List<PcSupplementDutyTtl> dutyTtls = ttlMapper.selectList(wrapperDuty);
        List<String> duty = new ArrayList<>();
        if (!ArrayUtils.isEmpyt(dutyTtls)) {
            duty = dutyTtls.stream()
                    .filter(Objects::nonNull)
                    .map(PcSupplementDutyTtl::getDutyName).collect(Collectors.toList());
        }
        /*封装返回*/
        Map<String, Object> map = new HashMap<>(3);
        map.put("blFlag", blFlag);
        map.put("dept", dept);
        map.put("duty", duty);
        return ResponseInfo.ok(map);
    }
}
